Backend Changelog
NHN On-Premise 백엔드(cone-watcher-backend) 변경 이력
Initial Setup — NHN 전용 기능 변경
추가된 기능
파트너 사용량 관리
파트너(MSP 업체)별 클라우드 서비스 이용량을 월 단위로 집계하고 과금하는 기능.
- 파트너 목록/상세 조회, 기본 할인율(0~100%) 및 할인 기간(시작월~종료월) 설정
apply_immediately=True시 미발행(Unissued) 상태 사용량의 할인율을 즉시 재계산- 파트너 사용량 상태: Origin → Unissued → Invoiced → Paid → Overdue
- 사용량 목록/상세 엑셀 다운로드
- 리셀러 타입: NHN Cloud, NHN InjeINC, Grumatic, 없음
- Worker 태스크: 회사별 월간 발행 청구서 수를 집계하여 건당 단가 산정 (30건 초과: 30,000원/건, 30건 이하: 27,500원/건, FREE_INVOICE_COUNT=0). 리셀러 할인율 적용 후 Origin + Unissued 이중 레코드 생성
- Scheduler:
partner_usage_task— cron 기반 자동 실행
회사 이메일 설정 관리
청구서 이메일 발송 시 본문에 삽입되는 커스텀 머리말(email_header)/꼬리말(email_footer) 설정.
company_settings컬렉션에 company_id 기준으로 저장- 설정이 없으면 자동 생성(upsert-on-read)
- 청구서 이메일 발송 시
CUSTOM_HEADER,CUSTOM_FOOTER파라미터로 본문에 삽입
파일 관리 API (로고/직인)
회사 로고 및 직인 이미지를 MongoDB GridFS 기반으로 업로드/관리하는 기능.
DefaultFSService(Singleton, GridFS 기반, company_id 인덱스)ImageFSService(이미지 검증 및 리사이징)LogoFSService,StampFSService(로고/직인 전용 구현)- 업로드 시 기존 파일 자동 교체, 메타데이터(원본 파일명, 확장자, 크기, 업로드일) 저장
거래명세서
청구서 기반 거래명세서 Excel 생성 및 다운로드. invoice_full.xlsx 템플릿 사용.
시스템 에러 로깅
error_log 컬렉션에 source(smtp/nhn_api/worker/scheduler), action, exception_type, message, traceback, context 필드로 에러 저장. TTL 90일 자동 삭제. SMTP 연결/발송 실패, NHN API 요청 실패, Worker 태스크 실패 등에 적용.
이메일 발송 로깅
invoice_deliveries 컬렉션에 발송 결과 저장. 필드: status(SUCCESS/FAILED), requested/accepted/refused recipients, cc/bcc recipients, sender_name, subject, attachments, error_message, smtp_context. TTL 1년. SMTP의 send_email() 반환값을 bool에서 dict로 변경하여 refused_recipients 등 상세 결과 추적.
스케줄러 (APScheduler)
APScheduler 기반 cron 스케줄러. 5개 정기 작업 등록:
nhn_invoice_task— NHN 청구서 자동 생성update_nhn_project_list_task— NHN 프로젝트 목록 동기화contract_expiration_task— 계약 만료 알림auto_suspend_expired_organizations— 만료 고객사 자동 중지partner_usage_task— 파트너 사용량 집계
수정된 기능
사용자/역할 체계
- 역할 계층: ROOT, SUPERUSER, ADMIN, MANAGER, CLIENT_ADMIN, CLIENT_USER (6단계)
- SUPERUSER 역할이 ROOT과 ADMIN 사이에 추가됨. Admin 포탈 접근 및 파트너 관리 권한 보유.
is_superuser프로퍼티 추가,includes_role()메서드에 SUPERUSER 체인 삽입CloudProviderType:Literal['aws', 'ncp', 'nhn']→Literal['nhn'](단일 CSP)NHNCloudType:Literal['NORMAL']→Literal['NORMAL', 'GOV'](GOV 타입 추가)
고객사(조직) — 계정 모델 재설계
NHN 파트너 이메일 기반의 단일 CSP 계정 구조.
NHNPartnerEmail(uid, email, discount_rate) +NHNPartnerAccount(org_id, org_name, org_type, org_status, project_id, project_name, project_type, project_status, discount_rate)- 계정 관리 단위가 프로젝트 단위에서 파트너 이메일 단위로 변경
cloud_accounts필드 타입:List[Union[AWSAccount, NCPAccount, NHNAccount]]→list[NHNPartnerAccount]partner_emails: list[NHNPartnerEmail]필드 추가cc_integrated_allow(CC 연동 허용) 필드 제거- 이메일 수신자 자동 결정:
get_default_recipients()(billing_email_option='primary'인 연락처),get_cc_recipients()(billing_email_option='cc'인 연락처) - 조직 생성 시 계정 연결 단계 제거 (별도 프로세스로 분리)
- 조직 목록 스키마:
number_of_aws_accounts,number_of_ncp_accounts→number_of_accounts단일 필드 - 조직 요약
by_csp:{'aws': 0, 'ncp': 0}→{'nhn': 0}
청구서
- 환율 관련 필드 제거:
exchange_rate_id,exchange_rate_value,exchange_rate_source(NHN은 원화 전용) org_cloud_cost필드 추가: 고객사 전체 청구서의cloud_cost.krw합산값을 각 청구서에 저장- 청구서 필터링 스키마 추가: 날짜 범위, 조직 ID 목록, 상태 목록, 청구서 ID 목록으로 복합 필터
- 대량 상태 변경 스키마 추가: 여러 청구서를 한번에 Invoiced로 변경하면서 이메일 발송, 보증금 처리 일괄 수행
- 자동완성 스키마 추가: 청구서 ID/고객사명 기반 검색
- 수신자 구조 변경:
email_list: list[str]→recipients,cc_recipients,bcc_recipients(To/CC/BCC 분리) - 이메일 발송 시 회사 설정(email_header/email_footer)을 본문에 삽입
- CSV 다운로드 기능 제거
청구서 PDF
- 인보이스 타입:
Union[AWSInvoice, NCPInvoice, NHNInvoice]→NHNInvoiceModel단일 - 로고 로딩: CDN URL 참조 →
LogoFSService에서 GridFS 파일 로드 후 base64 인코딩 - 커버 페이지에 NHN 원가(
ORIGIN_CLOUD_USAGE), NHN 할인액(CLOUD_DISCOUNT) 구분 표시 - 계정별 요약에
OriginUsage,CloudDiscount컬럼 추가 - 클라우드 사용 상세에 카운터 항목별
USAGE_COST,DISCOUNT_RATE,COST분리 표시 - Excel 템플릿:
invoice_consolidation.xlsx→invoice.xlsx,invoice_consolidation_full.xlsx→invoice_full.xlsx(멀티CSP 시트 로직 제거)
NHN 계정 API — 인증 방식 변경
- ID/PW 인증 전용(tenant_id, username, password, cloud_type).
NHNResellerClient사용. - 인증 정보를 config-level
NHNCredential로 관리. NORMAL/GOV 각각nhn,nhn_gov설정으로 분리. - 제거된 기능: 계정 계층 구조 조회, TemporaryData 기반 UI 생성 플로우, UUID 별도 업데이트, 사용자 정보 검증, 할당 프로젝트 목록 조회
- 추가된 기능: cloud_type(NORMAL/GOV) 지원, 중복 UUID 체크, account_name 변경
NHN 매출 API
- 매출 항목에
invoice_id필드 추가 NHNProjectExtra모델 추가: 프로젝트별 조정(project_extra.total_adjustment) 및 할인(project_discount.total_adjustment) 상세 내역 포함- 매출 그래프: purchase_month/supply_month 분리 → target_month 하나로 통합
- 매출 테이블: 삭제된 조직도 포함하여 조회 (
include_deleted=True) - 매출 매입 상세 API 추가: 특정 청구서의 프로젝트별 서비스>리전>상품 계층 매입 내역
Worker — 청구서 자동 생성 재설계
- 조직의
partner_emails순회 → 이메일별get_projects_by_email()→ CLOSED 상태/기존 프로젝트/이미 발행된 청구서 스킵 →partner.discount_rate적용. 기존 프로젝트는 건너뜀.
Worker — 계정 동기화 재설계
- 조직의
partner_emails순회 → 이메일별 프로젝트 목록 조회 → 신규/기존NHNPartnerAccount생성/갱신 → 사라진 프로젝트를 부가서비스/할인/계약에서 자동 제거 → 신규 프로젝트 발견 시(매월 4일 15:00 이후) 자동 청구서 생성 태스크 실행 - 태스크명 변경:
update_nhn_account_hierarchy→update_nhn_project_list(파라미터:account_uid→account_id+organization_id)
이메일 발송
- 클라이언트: AWS SES → SMTP 직접 연동 (
common/client/email/smtp.py) - 수신자: 단일(
recipient: str) → 다중(recipients: list[str]+ cc/bcc) - 로고: CDN URL →
LogoFSService(GridFS)에서 파일 존재 확인 후 URL 설정 - 발신자:
SENDER_NAME,SENDER_EMAIL,SENDER_ADDRESS,CUSTOM_SENDER파라미터 추가 - Jinja2 커스텀 필터:
nl2br(줄바꿈→BR),to_preview(HTML 태그 제거) - 영문 템플릿 전체 제거, 한국어 전용
- 이메일 제목: 하드코딩
[heka]→[{{APP_NAME}}]동적 치환 - 청구서 이메일 제목:
[{{COMPANY_NAME}}] {{BILLING_MONTH}} 청구서 - {{CUSTOMER_NAME}}
회사 모델
- 추가 필드:
reseller_type(NONE/NHN/INJE/GRMT),reseller_discount_rate(0~1),discount_start_month,discount_end_month is_trial기본값 True→False,trial_date기본값 변경,remove_prefix필드 제거
2026년 3월
03-11
- 청구서 자동 생성 스킵 조건 추가 (PoC #2):
org.options.invoice_creation이 False,org.partner_emails가 비어있음, 해당 프로젝트의 모든 계약이 만료된 경우 각각logger.warning으로 사유를 기록하고 건너뜀 - 초대 로그인 시간 기록 (PoC #4):
verify_user_invited_login메서드에서 토큰 생성 전update_last_login()호출 추가. 기존에는 일반 로그인에서만 기록하고 초대 로그인에서는 누락 - 계약 변경 시 고객사 상태 자동 재판단 (PoC #5): 계약 수정/삭제 후
_reevaluate_organization_status()호출.auto_status_change옵션이 True일 때, 모든 계약이 만료이면 in-use/poc → suspended, 유효 계약이 하나라도 있으면 suspended → in-use로 변경 - 마지막 관리자 역할 변경 방지 (PoC #6): 대상 사용자가 ADMIN이고 다른 역할로 변경 요청 시, 해당 회사에 ADMIN 이상 사용자가 1명 이하이면
DeleteLastAdminException발생 - 고객사 목록 등록 역순 정렬 (PoC #10): 조회 시 최신 등록 순으로 정렬
- 계약 알림 일수 음수 방지 (PoC #11):
ContractSchema에ge=0제약 추가 - 크레딧 VAT 별도 금액 차감 (PoC #13):
supply = subtotal - deposit으로 공급가액 산출, VAT를supply * 0.1로 계산 (기존:subtotal * 0.1). PDF 커버에서 BALANCE_DUE 항목 제거, 크레딧을 할인 아래 별도 행으로 표시. "선납금" → "크레딧", "인보이스 합계" → "크레딧 차감액", "납부하실 금액 (VAT 별도)" → "(VAT 포함)"으로 용어 변경 - 프로젝트 선택 필터링 (PoC #16):
NHNPartnerEmail에selected_projects: list[SelectedProject]필드 추가. 계정 추가/수정 시 프로젝트 미리보기 API(POST /{org_id}/account/preview)로 이메일 기반 프로젝트 목록 조회 후 선택 저장. Worker 동기화 시selected_ids필터 적용하여 선택된 프로젝트만cloud_accounts에 포함. API에서 더 이상 조회되지 않는 프로젝트는available=False로 갱신.
03-12
- 프로젝트 필터링 후속 수정 (PoC #16): 파트너 이메일 확인 시 404/409 에러 처리 추가. 청구서 자동 생성 Worker에서
selected_ids필터가 실제 반영되도록 수정.
03-20
- "계정" → "프로젝트" 명칭 통일 (PoC #25): 청구서/이메일 템플릿 8개에서 "NHN Cloud 계정" → "NHN Cloud 프로젝트" 변경
- 부가서비스/할인에 프로젝트ID 표기 (PoC #22): PDF 부가서비스/할인 항목에 프로젝트ID 컬럼 추가
- 원 단위 통일 (PoC #42): 이메일 청구서 금액 표기를 원 단위로 통일
- 클라우드 요금 개요 섹션 (PoC #15): PDF에 "서비스별 클라우드 요금 개요" 테이블 추가 (컬럼: 프로젝트, 카테고리, 리전, 서비스, 금액). NHN 인보이스 data를 서비스>리전>상품 3단계로 순회하여 ProductTotalCost 출력. 기존 "서비스별 클라우드 요금"은 "서비스별 클라우드 상세 요금"으로 명칭 변경. "클라우드 제공사별 요약" 섹션 비활성화.
- 리포트 프로젝트별 청구 금액 (PoC #17):
ReportSettingsModel에projects: list[str]필터 추가. NHN 인보이스를 project_id 기준으로 그룹핑하여 월별cloud_cost + additional_cost - discount_cost합산. 엑셀에 "프로젝트별 청구금액" 시트 추가 (컬럼: 날짜, 고객사명, 프로젝트명, 금액).GET /organizations/cloud-accounts엔드포인트 추가. - 보조용언 띄어쓰기 통일 (PoC #41): 이메일 템플릿 내 보조용언 띄어쓰기 일괄 수정
- 표기 수정 반영: 청구서/리포트/매출 Excel/PDF에서 "미납" → "연체" 등 용어 수정
- 비밀번호 재설정 이메일 검증 (PoC #44): 비밀번호 재설정 시 이메일 불일치에 대한 명확한 오류 응답 추가
03-23
- 페르소나 로그인 활성화: Admin 라우터에서 페르소나(가장) 로그인 엔드포인트 활성화
03-24
- 클라우드 요금 개요 PDF 렌더링 수정 (PoC #15)
03-27
- 사용자 이메일 검증 API (PoC #66):
GET /users/check-email?email=엔드포인트 추가. 초대 전 이메일 중복 여부 사전 확인. - 초대 완료 오류 조건 강화 (PoC #60): 초대 완료 처리 시 404(이메일 불일치), 401(토큰 만료), 400(이미 설정 완료) 별 구체적 오류 응답
03-30
- Admin 권한 분리 (PoC #83): Admin 라우터 5개 엔드포인트의 scope를 ROOT, SUPERUSER로 제한
- Admin 청구서 단가 변경 (PoC #82): 단가 설정 스키마 추가
03-31
- 역할 체계 재정비 (PoC #83):
SUPERUSER→SYSTEM_ADMIN으로 명칭 변경. 역할 계층: ROOT > SYSTEM_ADMIN > ADMIN > MANAGER. 로그인 채널 분리 —is_admin_login=True시 SYSTEM_ADMIN 이상만 로그인 가능, 일반 콘솔에서 SYSTEM_ADMIN 차단. 사용자 목록에서 SYSTEM_ADMIN 비노출. 회사 설정/로고/NHN 계정 등 약 20개 엔드포인트에서 SUPERUSER scope 제거하여 ROOT > ADMIN > MANAGER 체계로 통일. - 거래명세서 수정: 거래명세서 생성 로직 수정
2026년 4월
04-10
- 크레딧 내역 수정: 청구서 PDF 최근 3개월 크레딧 내역의 계산/표시 오류 수정
04-13
- 최신 청구서 판별 로직 추가: 청구서 상세 API 응답에
IsLatest: bool필드 추가.nhn_invoice_service.get_latest_date_by_organization_id()로 해당 고객사의 최신 인보이스 날짜를 DB에서 조회하여, 현재 청구서의 date가 최신 날짜와 일치하면IsLatest=True. 프론트엔드에서 최신 월이 아닌 청구서의 금액 수정을 차단하는 데 사용.